﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using ProblemsSet;

namespace Euler
{
    public partial class _frmMain : Form
    {
        private const int _maxProblems = 267;
        private const string _problemsProject = "ProblemsSet";

        private int _cntSolved;
        private int _cntProblems;
        private IBaseProblem _currentProblem;

        public _frmMain()
        {
            InitializeComponent();
            InitData();
        }

        private void InitData()
        {
            _txtCondition.Text = "";
            _lblDescription.Text = "";
            _lblExists.Text = "";
            _tbResult.Text = "";
            _lblSolved.Text = "";
            _lblTime.Text = "";
            _lblAnswer.Text = "";
            _cbList.Items.Clear();
            FillDropDown();

        }

        private void FillDropDown()
        {
            int index = 0;
            for (var i = 1; i <= _maxProblems; i++)
            {
                var ProblemsAssembly = Assembly.LoadFrom(_problemsProject+".dll");

                var EntryPoint = ProblemsAssembly.CreateInstance(_problemsProject+".Problem_" + i) ?? new BaseProblem();
                if (EntryPoint.GetType().Name.Contains("Problem_"))
                {
                    _cntProblems++;
                    if (!((IBaseProblem) EntryPoint).IsSolved)
                        index = _cbList.Items.Count;
                }
                if (((IBaseProblem) EntryPoint).IsSolved) _cntSolved++;
                ((IBaseProblem) EntryPoint).Name = "Problem " + i;
                _cbList.Items.Add(EntryPoint);
            }
            _lblExists.Text = string.Format("Implemented {0} from {1} ({2}%)", _cntProblems, _maxProblems,
                                            100*_cntProblems/_maxProblems);
            _lblSolved.Text = string.Format("Solved {0} from {1} ({2}%)", _cntSolved, _maxProblems,
                                            100 * _cntProblems / _maxProblems);
            _cbList.SelectedIndex = index;
        }

        private void _cbList_SelectedIndexChanged(object sender, EventArgs e)
        {
            _currentProblem = _cbList.SelectedItem as IBaseProblem;
            InitItem();
        }

        private void InitItem()
        {
            if (_currentProblem == null)
            {
                _txtCondition.Text = "";
                _lblDescription.Text = "";
                _lblAnswer.Text = "";
            }
            else
            {
                _txtCondition.Text = _currentProblem.Problem;
                _lblDescription.Text = _currentProblem.Description;
                _lblAnswer.Text = _currentProblem.Answer != null ? _currentProblem.Answer.ToString() : "";
            }
            _tbResult.Text = "";
            _lblTime.Text = "";
        }

        private void _btnGet_Click(object sender, EventArgs e)
        {
            if (_currentProblem == null) return;
            var start = DateTime.Now;
            var res = _currentProblem.GetResult().ToString();
            _lblTime.Text = (DateTime.Now - start).ToString();
            _tbResult.Text = res;

        }

        private void _cbList_DrawItem(object sender, DrawItemEventArgs e)
        {
            try
            {
                if (e.Index < 0 || e.Index >= _cbList.Items.Count) return;
                var item = _cbList.Items[e.Index] as IBaseProblem;
                if (item == null) return;

                e.DrawBackground();

                using (var gr = e.Graphics)
                {
                    using (
                        var icon = item.IsSolved ? Properties.Resources.icon_solved : Properties.Resources.icon_unsolved
                        )
                    {
                        gr.DrawImage(icon,
                                     new Rectangle(e.Bounds.Left, e.Bounds.Top, _cbList.ItemHeight,
                                                   _cbList.ItemHeight),
                                     new Rectangle(0, 0, icon.Width, icon.Height), GraphicsUnit.Pixel);
                        gr.DrawString(item.Name, e.Font,
                                      new SolidBrush(_cbList.Items[e.Index].GetType().Name.Contains("Problem_")
                                                         ? e.ForeColor
                                                         : Color.Gray),
                                      _cbList.ItemHeight + 2 + e.Bounds.Left, e.Bounds.Top);
                    }
                }
                e.DrawFocusRectangle();
            }
            catch
            {
            }
        }

        private void _btnCheck_Click(object sender, EventArgs e)
        {
            Enabled = false;
            var prev = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
            var numbers = new List<string>();
            var cnt = 0;
            var totalTime = new TimeSpan(0);
            
            foreach (var o in _cbList.Items)
            {
                var problem = o as IBaseProblem;
                if (problem == null) continue;
                if (problem.Answer == null) continue;
                if (!problem.IsSolved) continue;
                cnt++;
                var start = DateTime.Now;
                if (problem.Answer.ToString() != problem.GetResult().ToString())
                    numbers.Add(problem.Name);
                var stop = DateTime.Now;
                totalTime += stop - start;
            }
            var res = "";
            foreach (var s in numbers)
            {
                res += Environment.NewLine+ s;
            }
            if (res == string.Empty) res = "All problems are passed!";
            else
            {
                res = "There were errors in following problems:" + res;
            }
            Cursor.Current = prev;
            Enabled = true;
            MessageBox.Show("Total were proved "+cnt+" problems in " + totalTime + Environment.NewLine + res);
        }

    }
}
